#ifndef _DKGL_TERRAIN_H_
#define _DKGL_TERRAIN_H_

#include "dkglVector3.h"
#include "COBJModel.h"

namespace DKGL
{

const unsigned int MAX_SEARCH_UNIT = 50; 
const unsigned char AVAILABLE					= 0x0;
const unsigned char BARRIER						= 0x1;
const unsigned char BOUNDARY					= 0x2;
const unsigned char NO_INTERSECTION		= 0x3;

typedef struct Movement_Tag
{
	Vector3 currentPosition;
	Vector3 newPosition;
	Vector3 probe;
	unsigned int currentTU;
	unsigned int newTU;
}Movement;


class Terrain;

class TerrainUnit
{
public:
	TerrainUnit();
	TerrainUnit(const TerrainUnit&);
	~TerrainUnit();

	void assignNeighbor(std::list<unsigned int>&); 
	void assignVertice(const Vector3*);
	
private:
	Vector3 m_pVertice[3];
	Vector3 m_Center;
	Vector3 m_Normal;
	unsigned short				m_nNumOfNeighbor;
	unsigned int					*m_pNeighbor;
	unsigned char				m_nRegionIdx;
	unsigned char				mType;
friend class Terrain;
};

class Terrain : public COBJModel
{
public:
	Terrain();
	virtual ~Terrain();

	void drawEntity();

	/*
		
	*/
	unsigned char surfacePoint2D(Movement& move,  bool bGlobalSearch = false);

	bool loadOBJ(const wstring& fname);
	bool loadTerrain(const wstring& fname);
	bool saveTerrain(const wstring& fname);

private:
	list<unsigned int> _findNeighbor(unsigned int) const;
	unsigned int _nearestNeighbor2Target(unsigned int src, const Vector3& target);
	unsigned int m_nNumOfUnit;
	unsigned char _surfacePoint2DGlobal(Movement& move);
	TerrainUnit *m_pTrnUnit;
};

// a class used to perform terrain following
class FeetOnTerrain : public BaseObject
{
public:
	enum MOVE_RESULT{ DONE, BLOCK, BOUNDARY, NOT_ON_TERRAIN} ;

	FeetOnTerrain();
	FeetOnTerrain(const FeetOnTerrain&);
	~FeetOnTerrain();

	MOVE_RESULT putOnTerrain(Terrain* trn, const Vector3& pos);
	void pickFromTerrain();
	MOVE_RESULT moveForward(float d);

	MOVE_RESULT move(const Vector3& dir, float offset = 0.0f);

	void setProbe(float d);

private:
	Terrain *m_pTerrain;
	unsigned int m_nCurrentTUIndex;
	float m_fProbe;
	bool m_bOnTerrain;
};

};

#endif